﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Mvc;
using System.Web.Script.Serialization;
using Antlr.Runtime;
using internal_website.App_Data;
using internal_website.Models;
using internal_website.Models.jQueryDataTables;
using log4net;

namespace internal_website.Controllers
{
    public class ComposerController : Controller
    {
        private static readonly ILog log = LogManager.GetLogger(typeof(ComposerController));
        private OrchestraSiteManagerContext db = new OrchestraSiteManagerContext();


        public ActionResult Index()
        {
            return View();
        }

        public ActionResult DataTablesAjaxHandler(Models.jQueryDataTables.jQueryDataTableParamModel param)
        {
            //http://www.codeproject.com/Articles/155422/jQuery-DataTables-and-ASP-NET-MVC-Integration-Part
            var filteredEntities = SearchCollectionBy(param.sSearch);
            var displayedEntities = filteredEntities.Skip(param.iDisplayStart).Take(param.iDisplayLength);

            var jsonResult = Json(new   {   param.sEcho,
                                            iTotalRecords = EntireCollection().Count(),
                                            iTotalDisplayRecords = filteredEntities.Count(),
                                            aaData = displayedEntities
                                        }, JsonRequestBehavior.AllowGet);

            
            var jq = new JQueryDataTablesAjaxHandler<Composer>();
            var str = jq.PropertyName((x => x.FirstName);
            jq.DataTablesAjaxHandler(param);
            return jsonResult;
        }





        private bool PatternIsFoundInAnyOfTheseStrings(List<string> stringsToExamine, string regexPtn)
        {
            var reg = new System.Text.RegularExpressions.Regex(regexPtn, RegexOptions.IgnoreCase);

            //does any condition satisfy the condition?
            var conditionSatisfied = stringsToExamine.Any(str => reg.IsMatch(str));
            return conditionSatisfied;
        }

        private bool AnyOfPatternsIsFoundInAnyOfTheseStringsToExamine(List<string> stringsToExamine, List<string> regPtns)
        {
            var anyOfPatternsIsFoundInAnyOfTheseStringsToExamine =
                regPtns.Any(currentPtn => PatternIsFoundInAnyOfTheseStrings(stringsToExamine, currentPtn));

            return anyOfPatternsIsFoundInAnyOfTheseStringsToExamine;
        }

        private IEnumerable<string[]> SearchCollectionBy(string sSearch)
        {
            var reg = sSearch == null ? new[] { ".*" } : sSearch.Split(' ');
            var entireCollection = EntireCollection();

            IEnumerable<string[]> query =
                entireCollection.Where(
                    c =>
                    AnyOfPatternsIsFoundInAnyOfTheseStringsToExamine(new List<string> {c.LastName, c.FirstName},
                                                                     new List<string>(reg)))
                                .Select(
                                    c =>
                                    new[]
                                        {
                                            Convert.ToString(c.Id), Convert.ToString(c.Active),
                                            Convert.ToString(c.LastName), Convert.ToString(c.FirstName)
                                        });

            return query;
        }

        //private IEnumerable<string[]> SearchCollectionBy(string sSearch)
        //{
        //    var regularExpression = new System.Text.RegularExpressions.Regex(sSearch == null ? ".*" : sSearch.Replace(" ", "|\\S+$"), RegexOptions.IgnoreCase);
        //    var entireCollection = EntireCollection();

        //    var query = from c in entireCollection
        //                where regularExpression.Matches(c.LastName + "\\s" + c.FirstName).Count > 0
        //                select new[] { Convert.ToString(c.ComposerId), Convert.ToString(c.Active), Convert.ToString(c.LastName), Convert.ToString(c.FirstName)};

        //    return query;
        //}

        private IEnumerable<Composer> EntireCollection()
        {
            var entireCollection = from c in db.Composers
                                   orderby c.LastName
                                   select c;
            return entireCollection;
        }

        private Composer GetComposerBy(int id = 0)
        {
            var composerId = (from c in db.Composers
                                        where c.Id == id
                                        select c).SingleOrDefault();
            return composerId;
        }

        public ActionResult _Details(int id= 0)
        {
            var composer = GetComposerBy(id);
            return PartialView("_Details", composer);
        }

        #region Create

        public ActionResult _Create()
        {
            return PartialView();
        }
        
        [HttpPost]
        [ValidateAntiForgeryToken]
        public JsonResult Create(Composer composer)
        {
            bool created = false;
            try
            {
                if (ModelState.IsValid)
                {
                    db.Composers.Add(composer);
                    db.SaveChanges();
                    created = true;
                }
            }
            catch (Exception e)
            {
                log.Error(e);
                return Json(e.Message);
            }
            return Json(created);
        }

        #endregion
        
        #region Edit

        public ActionResult _Edit(int id = 0)
        {
            Composer composer = db.Composers.Find(id);
            if (composer == null)
            {
                return HttpNotFound();
            }
            return PartialView("_Edit", composer);
        }
        
        [HttpPost]
        [ValidateAntiForgeryToken]
        public JsonResult Edit(Composer composer)
        {
            bool edited = false;
            try
            {
                if (ModelState.IsValid)
                {
                    db.Entry(composer).State = EntityState.Modified;
                    db.SaveChanges();
                    edited = true; 
                }
            }
            catch (Exception e)
            {
                log.Error(e);
                return Json(e.Message);
            }
            return Json(edited);
        }

        #endregion

        #region Delete

        [HttpPost]
        [ValidateAntiForgeryToken]
        public JsonResult Delete(int id)
        {
            bool deleted = false;
            try
            {
                if (ModelState.IsValid)
                {
                    Composer composer = db.Composers.Find(id);
                    db.Composers.Remove(composer);
                    db.SaveChanges();
                    deleted = true;
                }
            }
            catch (Exception e)
            {
                log.Error(e);
                return Json(e.Message);
            }
            return Json(deleted);
        }
        
        #endregion

        #region EmptyFormWithAntiForgeryToken

        public ActionResult Get_EmptyFormWithAntiForgeryToken()
        {
            return PartialView("_EmptyFormWithAntiForgeryToken");
        }

        #endregion

        #region Dispose

        protected override void Dispose(bool disposing)
        {
            db.Dispose();
            base.Dispose(disposing);
        }

        #endregion

    }
}